package belf.migrate.evaluate.helper;

import belf.migrate.api.taskconf.JobContext;
import belf.migrate.evaluate.model.EvaluateGrammarResult;
import belf.migrate.evaluate.model.EvaluateObjectsResult;
import belf.migrate.evaluate.model.EvaluateResult;
import belf.migrate.evaluate.model.EvaluateWholeResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * 语法评估和整体评估
 */
@Slf4j
public class EvaluateTool {

    private final EvaluateObjectsResult objectsResult;

    private final JobContext jobContext;

    public EvaluateTool(JobContext jobContext, EvaluateObjectsResult objectsResult) {
        this.jobContext = jobContext;
        this.objectsResult = objectsResult;
    }

    public EvaluateResult run() {
        EvaluateResult result = new EvaluateResult();
        result.setSinkCatalogs(jobContext.getTaskConf().getEvaluateConf().getSinkDbs());

        Map<String, Double> compatiblePercentMap;

        //内部对象评估
        result.setObjectsResult(objectsResult);
        compatiblePercentMap = getObjectScore();

        // 语法评估
        EvaluateGrammarTool grammarTool = new EvaluateGrammarTool(jobContext, objectsResult, 30);
        EvaluateGrammarResult grammarResult = grammarTool.run();
        result.setGrammarResult(grammarResult);
        compatiblePercentMap = sumScore(compatiblePercentMap, grammarResult.getCompatiblePercent());

        // 整体评估
        EvaluateWholeTool wholeTool = new EvaluateWholeTool(jobContext, objectsResult, 20);
        EvaluateWholeResult wholeResult = wholeTool.run();
        result.setWholeResult(wholeResult);
        compatiblePercentMap = sumScore(compatiblePercentMap, wholeResult.getCompatiblePercent());

        result.setCompatiblePercent(maxScoreMap(compatiblePercentMap));
        return result;
    }

    //获取内部对象的得分
    private Map<String, Double> getObjectScore() {

        Map<String, Double> result = new HashMap<>();

        Map<String, Map<String, Integer>> columnRiskMap = objectsResult.getColumnRisk();
        Map<String, Map<String, Integer>> functionRiskMap = objectsResult.getFunctionRisk();
        Map<String, Map<String, Integer>> indexRiskMap = objectsResult.getIndexRisk();

        for (String sinkCatalog : jobContext.getTaskConf().getEvaluateConf().getSinkDbs()) {
            int objectScore = 50;
            //不支持的对象类型
            if (objectsResult.getNoSupportObTypesMap() != null && !CollectionUtils.isEmpty(objectsResult.getNoSupportObTypesMap().get(sinkCatalog))) {
                objectScore -= 5 * objectsResult.getNoSupportObTypesMap().get(sinkCatalog).size();
            }
            Map<String, Integer> columnRisk = columnRiskMap.get(sinkCatalog);
            Map<String, Integer> functionRisk = functionRiskMap.get(sinkCatalog);
            Map<String, Integer> indexRisk = indexRiskMap.get(sinkCatalog);

            //列风险项
            if (columnRisk != null) {
                for (String key : columnRisk.keySet()) {
                    objectScore -= 3;
                    if (columnRisk.get(key) > 5) {
                        objectScore -= 2;
                    }
                }
            }

            //函数风险项
            if (functionRisk != null) {
                for (String key : functionRisk.keySet()) {
                    objectScore -= 2;
                    if (functionRisk.get(key) > 5) {
                        objectScore -= 2;
                    }
                }
            }

            //索引风险项
            if (indexRisk != null) {
                for (String key : indexRisk.keySet()) {
                    objectScore -= 1;
                    if (indexRisk.get(key) > 5) {
                        objectScore -= 2;
                    }
                }
            }

            result.put(sinkCatalog, (double) objectScore / 100);
        }


        return result;
    }

    public Map<String, Double> sumScore(Map<String, Double> map1, Map<String, Double> map2) {
        Map<String, Double> result = new HashMap<>();
        for (String key : map1.keySet()) {
            result.put(key, map1.get(key) + map2.get(key));
        }
        return result;
    }

    public Map<String, Double> maxScoreMap(Map<String, Double> map) {
        Map<String, Double> result = new HashMap<>();
        for (String key : map.keySet()) {
            result.put(key, Math.max(map.get(key), 0.6));
        }
        return result;
    }

}
